package com.xhx.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.apache.pdfbox.Loader;
import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.xhx.util.OpenDirUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * pdf转pic
 * 
 * @author xhx
 */
@RestController
@Slf4j
@RequestMapping("/pdf/pic")
public class PdfPictureController extends AbstractPdfPictureController {

	public PdfPictureController(ThreadPoolTaskExecutor executor) {
		super(executor, log);
	}

	/**
	 * 拆分pdf文件成多个jpg
	 * 
	 * @param file
	 * @param path
	 * @param prefix
	 * @param dpi
	 * @return
	 */
	@PostMapping("/split")
	public String split(@RequestParam MultipartFile file, @RequestParam String path,
			@RequestParam(required = false) String prefix, @RequestParam Integer dpi) {
		if (file.isEmpty()) {
			return "文件为空";
		}
		String nprefix;
		if (null == prefix) {
			nprefix = this.getFileName(file);
		} else {
			nprefix = prefix;
		}
		return this.processPdf(file, document -> {
			PDFRenderer pdfRenderer = new PDFRenderer(document);
			String outputDirPath = path + "/";
			File outputDir = new File(outputDirPath);
			if (!outputDir.exists()) {
				outputDir.mkdirs();
			}
			// 将每页PDF转换为JPG
			for (int page = 0; page < document.getNumberOfPages(); ++page) {
				this.split(outputDirPath, String.format("%s-%s.jpg", nprefix, page + 1), pdfRenderer, page, dpi);
			}
			OpenDirUtil.openDir(path);
			return "处理成功";
		}, e -> "Error occurred: " + e.getMessage());
	}

	/**
	 * 批量拆分pdf文件成多个jpg
	 * 
	 * @param path
	 * @param dpi
	 * @return
	 */
	@PostMapping("/batchSplit")
	public String batchSplit(@RequestParam String path, @RequestParam Integer dpi) {
		File dir = new File(path);
		if (!dir.exists() || !dir.isDirectory()) {
			return "路径不争取";
		}
		File[] files = dir.listFiles((d, name) -> name.toLowerCase().endsWith(".pdf"));
		if (files == null || files.length == 0) {
			return "路径下无pdf";
		}
		for (File file : files) {
			this.doSplit(file, dpi);
		}
		return String.format("已处理%s个pdf文件", files.length);
	}

	private void doSplit(File file, Integer dpi) {
		log.info("开始处理-{}", file.getAbsolutePath());
		String path = this.getDir(file);
		String name = this.getFileName(file);
		// 创建输出目录
		String outputDirPath = path + name + "/";
		File outputDir = new File(outputDirPath);
		if (!outputDir.exists()) {
			outputDir.mkdirs();
		}
		this.processPdf(file, document -> {
			PDFRenderer pdfRenderer = new PDFRenderer(document);
			// 将每页PDF转换为JPG
			for (int page = 0; page < document.getNumberOfPages(); ++page) {
				this.split(outputDirPath, String.format("%s-%s.jpg", name, page + 1), pdfRenderer, page, dpi);
			}
			return null;
		}, e -> "Error occurred: " + e.getMessage());
		log.info("结束处理-{}", file.getAbsolutePath());
	}

	/**
	 * 拆分pdf文件成多个jpg，并将两个图片合并成一张
	 * 
	 * @param file
	 * @param path
	 * @param prefix
	 * @param firstIndex
	 * @param secondIndex
	 * @param dpi
	 * @return
	 */
	@PostMapping("/merge")
	public String merge(@RequestParam MultipartFile file, @RequestParam String path,
			@RequestParam(required = false) String prefix, @RequestParam Integer firstIndex,
			@RequestParam Integer secondIndex, @RequestParam Integer dpi) {
		if (file.isEmpty()) {
			return "文件为空";
		}
		if (null == prefix) {
			prefix = this.getFileName(file);
		}
		String outputDirPath = path + "/";
		File outputDir = new File(outputDirPath);
		if (!outputDir.exists()) {
			outputDir.mkdirs();
		}
		firstIndex--;
		secondIndex--;
		try (PDDocument document = this.buildDocument(file)) {
			int total = document.getNumberOfPages();
			if (!checkPage(total, firstIndex) || !checkPage(total, firstIndex)) {
				return "页码超范围";
			}
			PDFRenderer pdfRenderer = new PDFRenderer(document);
			BufferedImage firstPageImage = pdfRenderer.renderImageWithDPI(firstIndex, dpi, ImageType.RGB);
			BufferedImage secondPageImage = pdfRenderer.renderImageWithDPI(secondIndex, dpi, ImageType.RGB);
			if (firstPageImage == null || secondPageImage == null) {
				return "PDF读取失败";
			}
			String fileName = String.format("%s-%s-%s.jpg", prefix, firstIndex + 1, secondIndex + 1);
			this.merge(outputDirPath, fileName, firstPageImage, secondPageImage);
			firstPageImage.flush();
			secondPageImage.flush();
			OpenDirUtil.openDir(outputDirPath);
			return "处理成功";
		} catch (IOException e) {
			log.error(e.getMessage(), e);
			return "Error occurred: " + e.getMessage();
		}
	}

	/**
	 * 批量拆分pdf文件成多个jpg，并将两个图片合并成一张
	 * 
	 * @param path
	 * @param dpi
	 * @param firstIndex
	 * @param secondIndex
	 * @return
	 */
	@PostMapping("/batchMerge")
	public String batchMerge(@RequestParam String path, @RequestParam Integer dpi, @RequestParam Integer firstIndex,
			@RequestParam Integer secondIndex) {
		File dir = new File(path);
		if (!dir.exists() || !dir.isDirectory()) {
			return "路径不争取";
		}
		File[] files = dir.listFiles((d, name) -> name.toLowerCase().endsWith(".pdf"));
		if (files == null || files.length == 0) {
			return "路径下无pdf";
		}
		for (File file : files) {
			this.doMerge(file, dpi, firstIndex - 1, secondIndex - 1);
		}
		return String.format("已处理%s个pdf文件", files.length);
	}

	private void doMerge(File file, Integer dpi, int firstIndex, int secondIndex) {
		log.info("开始处理-{}", file.getAbsolutePath());
		String path = this.getDir(file);
		String name = this.getFileName(file);
		// 创建输出目录
		String outputDirPath = path + name + "/";
		File outputDir = new File(outputDirPath);
		if (!outputDir.exists()) {
			outputDir.mkdirs();
		}
		try (PDDocument document = this.buildDocument(file)) {
			int total = document.getNumberOfPages();
			if (!checkPage(total, firstIndex) || !checkPage(total, firstIndex)) {
				log.info("页码超范围-{}", file.getAbsolutePath());
				return;
			}
			PDFRenderer pdfRenderer = new PDFRenderer(document);
			BufferedImage firstPageImage = pdfRenderer.renderImageWithDPI(firstIndex, dpi, ImageType.RGB);
			BufferedImage secondPageImage = pdfRenderer.renderImageWithDPI(secondIndex, dpi, ImageType.RGB);
			if (firstPageImage == null || secondPageImage == null) {
				log.info("PDF读取失败-{}", file.getAbsolutePath());
				return;
			}
			String fileName = String.format("%s-%s-%s.jpg", name, firstIndex + 1, secondIndex + 1);
			this.merge(outputDirPath, fileName, firstPageImage, secondPageImage);
			firstPageImage.flush();
			secondPageImage.flush();
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
		log.info("结束处理-{}", file.getAbsolutePath());
	}

	/**
	 * 拆分pdf文件成多个jpg，并将两个图片合并成一张,返回图片流
	 * 
	 * @param file
	 * @param firstIndex
	 * @param secondIndex
	 * @param dpi
	 * @return
	 */
	@PostMapping("/getMerge")
	public void getMerge(@RequestParam MultipartFile file, @RequestParam Integer firstIndex,
			@RequestParam Integer secondIndex, @RequestParam Integer dpi, HttpServletResponse response) {
		if (file.isEmpty()) {
			return;
		}
		firstIndex--;
		secondIndex--;
		try (PDDocument document = this.buildDocument(file)) {
			int total = document.getNumberOfPages();
			if (!checkPage(total, firstIndex) || !checkPage(total, firstIndex)) {
				return;
			}
			PDFRenderer pdfRenderer = new PDFRenderer(document);
			BufferedImage firstPageImage = pdfRenderer.renderImageWithDPI(firstIndex, dpi, ImageType.RGB);
			BufferedImage secondPageImage = pdfRenderer.renderImageWithDPI(secondIndex, dpi, ImageType.RGB);
			if (firstPageImage == null || secondPageImage == null) {
				return;
			}
			String fileName = String.format("%s-%s-%s.jpg", this.getFileName(file), firstIndex + 1, secondIndex + 1);
			this.getMerge(fileName, firstPageImage, secondPageImage, response);
			firstPageImage.flush();
			secondPageImage.flush();
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
	}

	/**
	 * 获取pdf总页数
	 * 
	 * @param file
	 * @param index
	 * @param dpi
	 * @return
	 */
	@PostMapping("/getPages")
	public Integer getPages(@RequestParam MultipartFile file) {
		if (file.isEmpty()) {
			return 0;
		}
		return this.processPdf(file, document -> {
			return document.getNumberOfPages();
		}, e -> 0);
	}

	/**
	 * 返回拆分pdf文件指定页码的图片流
	 * 
	 * @param file
	 * @param index
	 * @param dpi
	 * @param response
	 */
	@PostMapping("/preview")
	public void preview(@RequestParam MultipartFile file, @RequestParam Integer index, @RequestParam Integer dpi,
			HttpServletResponse response) {
		if (file.isEmpty()) {
			return;
		}
		index--;
		try (PDDocument document = this.buildDocument(file)) {
			PDFRenderer pdfRenderer = new PDFRenderer(document);
			int total = document.getNumberOfPages();
			if (!checkPage(total, index)) {
				return;
			}
			BufferedImage image = pdfRenderer.renderImageWithDPI(index, dpi, ImageType.RGB);
			this.preview(this.getFileName(file), image, response);
			image.flush();
			return;
		} catch (IOException e) {
			log.error(e.getMessage(), e);
		}
	}

}
